
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Conditional View Processing &#8212; Django 2.2.12.dev20200304094918 documentation</title>
    <link rel="stylesheet" href="../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="Cryptographic signing" href="signing.html" />
    <link rel="prev" title="Django’s cache framework" href="cache.html" />



 
<script type="text/javascript" src="../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../index.html">Django 2.2.12.dev20200304094918 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../index.html">Home</a>  |
        <a title="Table of contents" href="../contents.html">Table of contents</a>  |
        <a title="Global index" href="../genindex.html">Index</a>  |
        <a title="Module index" href="../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="cache.html" title="Django’s cache framework">previous</a>
     |
    <a href="index.html" title="Using Django" accesskey="U">up</a>
   |
    <a href="signing.html" title="Cryptographic signing">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="topics-conditional-view-processing">
            
  <div class="section" id="s-conditional-view-processing">
<span id="conditional-view-processing"></span><h1>Conditional View Processing<a class="headerlink" href="#conditional-view-processing" title="Permalink to this headline">¶</a></h1>
<p>HTTP clients can send a number of headers to tell the server about copies of a
resource that they have already seen. This is commonly used when retrieving a
Web page (using an HTTP <code class="docutils literal notranslate"><span class="pre">GET</span></code> request) to avoid sending all the data for
something the client has already retrieved. However, the same headers can be
used for all HTTP methods (<code class="docutils literal notranslate"><span class="pre">POST</span></code>, <code class="docutils literal notranslate"><span class="pre">PUT</span></code>, <code class="docutils literal notranslate"><span class="pre">DELETE</span></code>, etc.).</p>
<p>For each page (response) that Django sends back from a view, it might provide
two HTTP headers: the <code class="docutils literal notranslate"><span class="pre">ETag</span></code> header and the <code class="docutils literal notranslate"><span class="pre">Last-Modified</span></code> header. These
headers are optional on HTTP responses. They can be set by your view function,
or you can rely on the <a class="reference internal" href="../ref/middleware.html#django.middleware.http.ConditionalGetMiddleware" title="django.middleware.http.ConditionalGetMiddleware"><code class="xref py py-class docutils literal notranslate"><span class="pre">ConditionalGetMiddleware</span></code></a>
middleware to set the <code class="docutils literal notranslate"><span class="pre">ETag</span></code> header.</p>
<p>When the client next requests the same resource, it might send along a header
such as either <a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-3.3">If-modified-since</a> or <a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-3.4">If-unmodified-since</a>, containing the
date of the last modification time it was sent, or either <a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-3.1">If-match</a> or
<a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-3.2">If-none-match</a>, containing the last <code class="docutils literal notranslate"><span class="pre">ETag</span></code> it was sent.
If the current version of the page matches the <code class="docutils literal notranslate"><span class="pre">ETag</span></code> sent by the client, or
if the resource has not been modified, a 304 status code can be sent back,
instead of a full response, telling the client that nothing has changed.
Depending on the header, if the page has been modified or does not match the
<code class="docutils literal notranslate"><span class="pre">ETag</span></code> sent by the client, a 412 status code (Precondition Failed) may be
returned.</p>
<p>When you need more fine-grained control you may use per-view conditional
processing functions.</p>
<div class="section" id="s-the-condition-decorator">
<span id="s-conditional-decorators"></span><span id="the-condition-decorator"></span><span id="conditional-decorators"></span><h2>The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator<a class="headerlink" href="#the-condition-decorator" title="Permalink to this headline">¶</a></h2>
<p>Sometimes (in fact, quite often) you can create functions to rapidly compute the <a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-2.3">ETag</a>
value or the last-modified time for a resource, <strong>without</strong> needing to do all
the computations needed to construct the full view. Django can then use these
functions to provide an “early bailout” option for the view processing.
Telling the client that the content has not been modified since the last
request, perhaps.</p>
<p>These two functions are passed as parameters to the
<code class="docutils literal notranslate"><span class="pre">django.views.decorators.http.condition</span></code> decorator. This decorator uses
the two functions (you only need to supply one, if you can’t compute both
quantities easily and quickly) to work out if the headers in the HTTP request
match those on the resource. If they don’t match, a new copy of the resource
must be computed and your normal view is called.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator’s signature looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">condition</span><span class="p">(</span><span class="n">etag_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">last_modified_func</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>The two functions, to compute the ETag and the last modified time, will be
passed the incoming <code class="docutils literal notranslate"><span class="pre">request</span></code> object and the same parameters, in the same
order, as the view function they are helping to wrap. The function passed
<code class="docutils literal notranslate"><span class="pre">last_modified_func</span></code> should return a standard datetime value specifying the
last time the resource was modified, or <code class="docutils literal notranslate"><span class="pre">None</span></code> if the resource doesn’t
exist. The function passed to the <code class="docutils literal notranslate"><span class="pre">etag</span></code> decorator should return a string
representing the <a class="reference external" href="https://tools.ietf.org/html/rfc7232#section-2.3">ETag</a> for the resource, or <code class="docutils literal notranslate"><span class="pre">None</span></code> if it doesn’t exist.</p>
<p>The decorator sets the <code class="docutils literal notranslate"><span class="pre">ETag</span></code> and <code class="docutils literal notranslate"><span class="pre">Last-Modified</span></code> headers on the response
if they are not already set by the view and if the request’s method is safe
(<code class="docutils literal notranslate"><span class="pre">GET</span></code> or <code class="docutils literal notranslate"><span class="pre">HEAD</span></code>).</p>
<p>Using this feature usefully is probably best explained with an example.
Suppose you have this pair of models, representing a simple blog system:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">datetime</span>
<span class="kn">from</span> <span class="nn">django.db</span> <span class="k">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Blog</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="o">...</span>

<span class="k">class</span> <span class="nc">Entry</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">blog</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span><span class="n">Blog</span><span class="p">,</span> <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">)</span>
    <span class="n">published</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateTimeField</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">)</span>
    <span class="o">...</span>
</pre></div>
</div>
<p>If the front page, displaying the latest blog entries, only changes when you
add a new blog entry, you can compute the last modified time very quickly. You
need the latest <code class="docutils literal notranslate"><span class="pre">published</span></code> date for every entry associated with that blog.
One way to do this would be:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">latest_entry</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">blog_id</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">Entry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">blog</span><span class="o">=</span><span class="n">blog_id</span><span class="p">)</span><span class="o">.</span><span class="n">latest</span><span class="p">(</span><span class="s2">&quot;published&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">published</span>
</pre></div>
</div>
<p>You can then use this function to provide early detection of an unchanged page
for your front page view:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.decorators.http</span> <span class="k">import</span> <span class="n">condition</span>

<span class="nd">@condition</span><span class="p">(</span><span class="n">last_modified_func</span><span class="o">=</span><span class="n">latest_entry</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">front_page</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">blog_id</span><span class="p">):</span>
    <span class="o">...</span>
</pre></div>
</div>
<div class="admonition-be-careful-with-the-order-of-decorators admonition">
<p class="first admonition-title">Be careful with the order of decorators</p>
<p class="last">When <code class="docutils literal notranslate"><span class="pre">condition()</span></code> returns a conditional response, any decorators below
it will be skipped and won’t apply to the response. Therefore, any
decorators that need to apply to both the regular view response and a
conditional response must be above <code class="docutils literal notranslate"><span class="pre">condition()</span></code>. In particular,
<a class="reference internal" href="http/decorators.html#django.views.decorators.vary.vary_on_cookie" title="django.views.decorators.vary.vary_on_cookie"><code class="xref py py-func docutils literal notranslate"><span class="pre">vary_on_cookie()</span></code></a>,
<a class="reference internal" href="http/decorators.html#django.views.decorators.vary.vary_on_headers" title="django.views.decorators.vary.vary_on_headers"><code class="xref py py-func docutils literal notranslate"><span class="pre">vary_on_headers()</span></code></a>, and
<a class="reference internal" href="http/decorators.html#django.views.decorators.cache.cache_control" title="django.views.decorators.cache.cache_control"><code class="xref py py-func docutils literal notranslate"><span class="pre">cache_control()</span></code></a> should come first
because <span class="target" id="index-0"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7232.html#section-4.1"><strong>RFC 7232</strong></a> requires that the headers they
set be present on 304 responses.</p>
</div>
</div>
<div class="section" id="s-shortcuts-for-only-computing-one-value">
<span id="shortcuts-for-only-computing-one-value"></span><h2>Shortcuts for only computing one value<a class="headerlink" href="#shortcuts-for-only-computing-one-value" title="Permalink to this headline">¶</a></h2>
<p>As a general rule, if you can provide functions to compute <em>both</em> the ETag and
the last modified time, you should do so. You don’t know which headers any
given HTTP client will send you, so be prepared to handle both. However,
sometimes only one value is easy to compute and Django provides decorators
that handle only ETag or only last-modified computations.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">django.views.decorators.http.etag</span></code> and
<code class="docutils literal notranslate"><span class="pre">django.views.decorators.http.last_modified</span></code> decorators are passed the same
type of functions as the <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator. Their signatures are:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">etag</span><span class="p">(</span><span class="n">etag_func</span><span class="p">)</span>
<span class="n">last_modified</span><span class="p">(</span><span class="n">last_modified_func</span><span class="p">)</span>
</pre></div>
</div>
<p>We could write the earlier example, which only uses a last-modified function,
using one of these decorators:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@last_modified</span><span class="p">(</span><span class="n">latest_entry</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">front_page</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">blog_id</span><span class="p">):</span>
    <span class="o">...</span>
</pre></div>
</div>
<p>…or:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">front_page</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">blog_id</span><span class="p">):</span>
    <span class="o">...</span>
<span class="n">front_page</span> <span class="o">=</span> <span class="n">last_modified</span><span class="p">(</span><span class="n">latest_entry</span><span class="p">)(</span><span class="n">front_page</span><span class="p">)</span>
</pre></div>
</div>
<div class="section" id="s-use-condition-when-testing-both-conditions">
<span id="use-condition-when-testing-both-conditions"></span><h3>Use <code class="docutils literal notranslate"><span class="pre">condition</span></code> when testing both conditions<a class="headerlink" href="#use-condition-when-testing-both-conditions" title="Permalink to this headline">¶</a></h3>
<p>It might look nicer to some people to try and chain the <code class="docutils literal notranslate"><span class="pre">etag</span></code> and
<code class="docutils literal notranslate"><span class="pre">last_modified</span></code> decorators if you want to test both preconditions. However,
this would lead to incorrect behavior.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Bad code. Don&#39;t do this!</span>
<span class="nd">@etag</span><span class="p">(</span><span class="n">etag_func</span><span class="p">)</span>
<span class="nd">@last_modified</span><span class="p">(</span><span class="n">last_modified_func</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="c1"># ...</span>

<span class="c1"># End of bad code.</span>
</pre></div>
</div>
<p>The first decorator doesn’t know anything about the second and might
answer that the response is not modified even if the second decorators would
determine otherwise. The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator uses both callback functions
simultaneously to work out the right action to take.</p>
</div>
</div>
<div class="section" id="s-using-the-decorators-with-other-http-methods">
<span id="using-the-decorators-with-other-http-methods"></span><h2>Using the decorators with other HTTP methods<a class="headerlink" href="#using-the-decorators-with-other-http-methods" title="Permalink to this headline">¶</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator is useful for more than only <code class="docutils literal notranslate"><span class="pre">GET</span></code> and
<code class="docutils literal notranslate"><span class="pre">HEAD</span></code> requests (<code class="docutils literal notranslate"><span class="pre">HEAD</span></code> requests are the same as <code class="docutils literal notranslate"><span class="pre">GET</span></code> in this
situation). It can also be used to provide checking for <code class="docutils literal notranslate"><span class="pre">POST</span></code>,
<code class="docutils literal notranslate"><span class="pre">PUT</span></code> and <code class="docutils literal notranslate"><span class="pre">DELETE</span></code> requests. In these situations, the idea isn’t to return
a “not modified” response, but to tell the client that the resource they are
trying to change has been altered in the meantime.</p>
<p>For example, consider the following exchange between the client and server:</p>
<ol class="arabic simple">
<li>Client requests <code class="docutils literal notranslate"><span class="pre">/foo/</span></code>.</li>
<li>Server responds with some content with an ETag of <code class="docutils literal notranslate"><span class="pre">&quot;abcd1234&quot;</span></code>.</li>
<li>Client sends an HTTP <code class="docutils literal notranslate"><span class="pre">PUT</span></code> request to <code class="docutils literal notranslate"><span class="pre">/foo/</span></code> to update the
resource. It also sends an <code class="docutils literal notranslate"><span class="pre">If-Match:</span> <span class="pre">&quot;abcd1234&quot;</span></code> header to specify
the version it is trying to update.</li>
<li>Server checks to see if the resource has changed, by computing the ETag
the same way it does for a <code class="docutils literal notranslate"><span class="pre">GET</span></code> request (using the same function).
If the resource <em>has</em> changed, it will return a 412 status code,
meaning “precondition failed”.</li>
<li>Client sends a <code class="docutils literal notranslate"><span class="pre">GET</span></code> request to <code class="docutils literal notranslate"><span class="pre">/foo/</span></code>, after receiving a 412
response, to retrieve an updated version of the content before updating
it.</li>
</ol>
<p>The important thing this example shows is that the same functions can be used
to compute the ETag and last modification values in all situations. In fact,
you <strong>should</strong> use the same functions, so that the same values are returned
every time.</p>
<div class="admonition-validator-headers-with-non-safe-request-methods admonition">
<p class="first admonition-title">Validator headers with non-safe request methods</p>
<p class="last">The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator only sets validator headers (<code class="docutils literal notranslate"><span class="pre">ETag</span></code> and
<code class="docutils literal notranslate"><span class="pre">Last-Modified</span></code>) for safe HTTP methods, i.e. <code class="docutils literal notranslate"><span class="pre">GET</span></code> and <code class="docutils literal notranslate"><span class="pre">HEAD</span></code>. If you
wish to return them in other cases, set them in your view. See
<span class="target" id="index-1"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7231.html#section-4.3.4"><strong>RFC 7231#section-4.3.4</strong></a> to learn about the distinction between setting a
validator header in response to requests made with <code class="docutils literal notranslate"><span class="pre">PUT</span></code> versus <code class="docutils literal notranslate"><span class="pre">POST</span></code>.</p>
</div>
</div>
<div class="section" id="s-comparison-with-middleware-conditional-processing">
<span id="comparison-with-middleware-conditional-processing"></span><h2>Comparison with middleware conditional processing<a class="headerlink" href="#comparison-with-middleware-conditional-processing" title="Permalink to this headline">¶</a></h2>
<p>Django provides simple and straightforward conditional <code class="docutils literal notranslate"><span class="pre">GET</span></code> handling via
<a class="reference internal" href="../ref/middleware.html#django.middleware.http.ConditionalGetMiddleware" title="django.middleware.http.ConditionalGetMiddleware"><code class="xref py py-class docutils literal notranslate"><span class="pre">django.middleware.http.ConditionalGetMiddleware</span></code></a>. While being easy to
use and suitable for many situations, the middleware has limitations for
advanced usage:</p>
<ul class="simple">
<li>It’s applied globally to all views in your project.</li>
<li>It doesn’t save you from generating the response, which may be expensive.</li>
<li>It’s only appropriate for HTTP <code class="docutils literal notranslate"><span class="pre">GET</span></code> requests.</li>
</ul>
<p>You should choose the most appropriate tool for your particular problem here.
If you have a way to compute ETags and modification times quickly and if some
view takes a while to generate the content, you should consider using the
<code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator described in this document. If everything already runs
fairly quickly, stick to using the middleware and the amount of network
traffic sent back to the clients will still be reduced if the view hasn’t
changed.</p>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Conditional View Processing</a><ul>
<li><a class="reference internal" href="#the-condition-decorator">The <code class="docutils literal notranslate"><span class="pre">condition</span></code> decorator</a></li>
<li><a class="reference internal" href="#shortcuts-for-only-computing-one-value">Shortcuts for only computing one value</a><ul>
<li><a class="reference internal" href="#use-condition-when-testing-both-conditions">Use <code class="docutils literal notranslate"><span class="pre">condition</span></code> when testing both conditions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-decorators-with-other-http-methods">Using the decorators with other HTTP methods</a></li>
<li><a class="reference internal" href="#comparison-with-middleware-conditional-processing">Comparison with middleware conditional processing</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="cache.html"
                        title="previous chapter">Django’s cache framework</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="signing.html"
                        title="next chapter">Cryptographic signing</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../_sources/topics/conditional-view-processing.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Mar 04, 2020</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="cache.html" title="Django’s cache framework">previous</a>
     |
    <a href="index.html" title="Using Django" accesskey="U">up</a>
   |
    <a href="signing.html" title="Cryptographic signing">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>